package dou.net.protocol;

import dou.io.ByteArrayInput;
import dou.io.IDataInput;
import dou.net.socket.AbstractClientSocket;
import dou.net.socket.IPacketBuffer;
import dou.net.socket.IServerSocket;
import dou.net.socket.InvalidProtocolException;
import dou.utils.ZLibUtil;

import java.io.IOException;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

/**
 * 实现了协议解析的功能
 * @author wizardc
 */
public abstract class AbstractProtocolClientSocket extends AbstractClientSocket
{
    /**
     * 构造函数
     * @param server 套接字服务对象
     * @param selector 套接字通道的 Selector 对象
     * @param socketChannel 套接字客户端的套接字通道对象
     * @throws IOException 当出现 IO 异常时抛出该异常
     */
    public AbstractProtocolClientSocket(IServerSocket server, Selector selector, SocketChannel socketChannel) throws IOException
    {
        super(server, selector, socketChannel);
    }

    @Override
    protected void packetArriveHandler(IPacketBuffer protocolPacket) throws InvalidProtocolException
    {
        IDataInput input = new ByteArrayInput(protocolPacket.toByteBuffer());
        if(checkMessageValid(input))
        {
            boolean compress = input.readBoolean();
            int msgID = input.readInt();
            int msgNum = input.readInt();
            byte[] bytes = new byte[input.bytesAvailable()];
            input.readBytes(bytes);
            if (compress)
            {
                bytes = ZLibUtil.decompress(bytes);
            }
            IProtocol protocol = ProtocolManager.getInstance().getProtocol(msgID);
            if(protocol != null)
            {
                protocol.messageHandler(msgID, msgNum, bytes, this);
            }
        }
        else
        {
            throw new InvalidProtocolException("This message is invalid!");
        }
    }

    /**
     * 验证数据是否有效
     * @param input 获取的消息数据
     * @return 数据是否有效
     */
    protected abstract boolean checkMessageValid(IDataInput input);
}
